﻿using System;
using System.Collections.Generic;
using System.Text;


namespace Teal.Compiler {

    /// <summary>
    /// 提供预定义类型的引用。
    /// </summary>
    public static partial class PredefinedTypes {

        #region 特殊类型

        /// <summary>
        /// 表示一个特殊类型。
        /// </summary>
        private sealed class SpeicalTypeReference : TypeReference {

            /// <summary>
            /// 获取当前成员的类型。
            /// </summary>
            public sealed override MemberType memberType {
                get {
                    return MemberType.specailType;
                }
            }

            public SpeicalTypeReference(string name)
                : base(MemberType.specailType) {
                this.name = name;
            }

            /// <summary>
            /// 将当前成员的完整限定名写入字符串缓存。
            /// </summary>
            /// <param name="buffer">用于写入的缓冲区对象。</param>
            public sealed override void writeSignature(StringBuilder buffer) {
                buffer.Append(name);
            }

        }

        /// <summary>
        /// 表示空类型。
        /// </summary>
        public static TypeReference @void = new SpeicalTypeReference("void");

        /// <summary>
        /// 表示自动推导类型。
        /// </summary>
        public static TypeReference @var = new SpeicalTypeReference("var");

        /// <summary>
        /// 获取动态泛型参数的版本。
        /// </summary>
        public static readonly MemberReference.GenericParameter[] argListParameters = new MemberReference.GenericParameter[1] { new MemberReference.GenericParameter() { name = "..." } };

        #endregion

        #region 约束类型

        /// <summary>
        /// 表示 class 约束。
        /// </summary>
        public static TypeReference classConstraint = new TypeReference(MemberType.constraintType) {
            name = "class"
        };

        /// <summary>
        /// 表示 struct 约束。
        /// </summary>
        public static TypeReference structConstraint = new TypeReference(MemberType.constraintType) {
            name = "struct"
        };

        /// <summary>
        /// 表示 enum 约束。
        /// </summary>
        public static TypeReference enumConstraint = new TypeReference(MemberType.constraintType) {
            name = "enum"
        };

        /// <summary>
        /// 表示默认构造函数约束。
        /// </summary>
        public static TypeReference defaultConstructorConstraint = new TypeReference(MemberType.constraintType) {
            name = "new()"
        };

        #endregion

        #region 底层类型

        /// <summary>
        /// 表示由关键字直接表示的内置类型。
        /// </summary>
        private sealed class InternalTypeReference : TypeReference {

            public InternalTypeReference(string name)
                : base(MemberType.@class) {
                this.name = name;
            }

            /// <summary>
            /// 将当前成员的完整限定名写入字符串缓存。
            /// </summary>
            /// <param name="buffer">用于写入的缓冲区对象。</param>
            public override void writeSignature(StringBuilder buffer) {
                buffer.Append(name);
            }

        }

        /// <summary>
        /// 获取预定义的 Object 类型。
        /// </summary>
        public static TypeReference System_Object = new InternalTypeReference("object");

        /// <summary>
        /// 获取预定义的 ValueType 类型。
        /// </summary>
        public static TypeReference System_ValueType = new TypeReference(MemberType.@class) {
            name = "ValueType",
            baseClass = System_ValueType
        };

        private static MemberReference.GenericParameter[] T {
            get {
                return new MemberReference.GenericParameter[] {
                    new MemberReference.GenericParameter(){
                        name = "T"
                    }
                };
            }
        }

        /// <summary>
        /// 获取预定义的 Enum&lt;T&gt; 类型。
        /// </summary>
        public static GenericTypeDefinitionReference System_Enum_T = new GenericTypeDefinitionReference(MemberType.@class, T) {
            name = "Enum",
            baseClass = System_ValueType
        };

        private class PtrTTypeReference : GenericTypeDefinitionReference {

            public PtrTTypeReference()
                : base(MemberType.@struct, T) {
                name = "Ptr";
                baseClass = System_ValueType;
            }

            ///// <summary>
            ///// 当被子类重写时，负责创建新的泛型。
            ///// </summary>
            ///// <param name="genericArguments">当前泛型的实参。</param>
            ///// <returns>新生成的泛型。</returns>
            //protected override GenericTypeReference createGenericType(TypeReference[] genericArguments) {
            //    var result = new PtrTypeReference(this, genericArguments);
            //    result.memberDefinition = memberDefinition;
            //    result.parentContainer = parentContainer;
            //    result.predefinedAnnotations = predefinedAnnotations;
            //    result.modifiers = modifiers;
            //    result.name = ResolveHelper.getGenericName(name, genericArguments);
            //    result.members = cloneMembers();
            //    return result;
            //}

        }

        private class PtrTypeReference : GenericTypeReference {

            /// <summary>
            /// 获取当前类型对应的基础类型。
            /// </summary>
            public override PrimitiveType primitiveType {
                get {
                    return PrimitiveType.ptr;
                }
            }

            public PtrTypeReference(PtrTTypeReference genericDefinitionType, TypeReference[] elementType)
                : base(genericDefinitionType, elementType) {

            }

            /// <summary>
            /// 将当前成员的完整限定名写入字符串缓存。
            /// </summary>
            /// <param name="buffer">用于写入的缓冲区对象。</param>
            public override void writeSignature(StringBuilder buffer) {
                genericArguments[0].writeSignature(buffer);
                buffer.Append('*');
            }

        }

        /// <summary>
        /// 获取预定义的 Ptr&lt;T&gt; 类型。
        /// </summary>
        public static GenericTypeDefinitionReference System_Ptr_T = new PtrTTypeReference();

        private class ArrayTTypeReference : GenericTypeDefinitionReference {

            public ArrayTTypeReference()
                : base(MemberType.@class, T) {
                name = "Array";
                baseClass = System_ValueType;
            }

            ///// <summary>
            ///// 当被子类重写时，负责创建新的泛型。
            ///// </summary>
            ///// <param name="genericArguments">当前泛型的实参。</param>
            ///// <returns>新生成的泛型。</returns>
            //protected override GenericTypeReference createGenericType(TypeReference[] genericArguments) {
            //    var result = new ArrayTypeReference(this, genericArguments);
            //    result.memberDefinition = memberDefinition;
            //    result.parentContainer = parentContainer;
            //    result.predefinedAnnotations = predefinedAnnotations;
            //    result.modifiers = modifiers;
            //    result.name = ResolveHelper.getGenericName(name, genericArguments);
            //    result.members = cloneMembers();
            //    return result;
            //}

        }

        private class ArrayTypeReference : GenericTypeReference {

            public ArrayTypeReference(ArrayTTypeReference genericDefinitionType, TypeReference[] elementType)
                : base(genericDefinitionType, elementType) {

            }

            /// <summary>
            /// 将当前成员的完整限定名写入字符串缓存。
            /// </summary>
            /// <param name="buffer">用于写入的缓冲区对象。</param>
            public override void writeSignature(StringBuilder buffer) {
                genericArguments[0].writeSignature(buffer);
                buffer.Append("[]");
            }

        }

        /// <summary>
        /// 获取预定义的 Array&lt;T&gt; 类型。
        /// </summary>
        public static GenericTypeDefinitionReference System_Array_T = new ArrayTTypeReference();

        /// <summary>
        /// 获取预定义的 Func 类型。
        /// </summary>
        public static TypeReference System_Func = new TypeReference(MemberType.@class) {
            name = "Func",
            baseClass = System_Object
        };

        /// <summary>
        /// 获取预定义的 Func&lt;T&gt; 类型。
        /// </summary>
        public static GenericTypeDefinitionReference System_Func_T = new GenericTypeDefinitionReference(MemberType.@struct, argListParameters) {
            name = "Func",
            baseClass = System_ValueType
        };

        /// <summary>
        /// 获取预定义的 Func.Ref&lt;T&gt; 类型。
        /// </summary>
        public static GenericTypeDefinitionReference System_Ref_T = new GenericTypeDefinitionReference(MemberType.@struct, T) {
            name = "Ref",
            baseClass = System_ValueType
        };

        /// <summary>
        /// 获取预定义的 Func.Out&lt;T&gt; 类型。
        /// </summary>
        public static GenericTypeDefinitionReference System_Func_Out_T = new GenericTypeDefinitionReference(MemberType.@struct, T) {
            name = "Out",
            baseClass = System_ValueType
        };

        private class TupleTypeReference : GenericTypeDefinitionReference {

            public TupleTypeReference()
                : base((MemberType) MemberType.@class, (GenericParameter[]) PredefinedTypes.argListParameters) {
                name = "Tuple";
                baseClass = System_ValueType;
            }

            ///// <summary>
            ///// 当被子类重写时，负责创建新的泛型。
            ///// </summary>
            ///// <param name="genericArguments">当前泛型的实参。</param>
            ///// <returns>新生成的泛型。</returns>
            //protected override GenericTypeReference createGenericType(TypeReference[] genericArguments) {
            //    var result = base.createGenericType(genericArguments);
            //    var id = 1;
            //    foreach (var type in genericArguments) {
            //        result.addMember(new FieldReference() {
            //            returnType = type,
            //            name = "item" + id++,
            //        });
            //    }
            //    return result;
            //}

        }

        /// <summary>
        /// 获取预定义的 Tuple&lt;...&gt; 类型。
        /// </summary>
        public static GenericTypeDefinitionReference System_Tuple_T = new TupleTypeReference();

        /// <summary>
        /// 获取预定义的 Event&lt;...&gt; 类型。
        /// </summary>
        public static GenericTypeDefinitionReference System_Event_T = new GenericTypeDefinitionReference(MemberType.@class, new MemberReference.GenericParameter[] {
            new MemberReference.GenericParameter(){
                name = "TEventArgs"
            }
        }) {
            name = "Event",
            baseClass = System_Object
        };

        /// <summary>
        /// 获取预定义的 Event 类型。
        /// </summary>
        public static TypeReference System_Event = new TypeReference(MemberType.@class) {
            name = "Event",
            baseClass = System_Object
        };

        #endregion

        #region 基础类型

        /// <summary>
        /// 表示一个基础类型。
        /// </summary>
        private class PrimitiveTypeReference : TypeReference {

            /// <summary>
            /// 当前类型对应的基础类型。
            /// </summary>
            PrimitiveType _primitiveType;

            /// <summary>
            /// 获取当前类型对应的基础类型。
            /// </summary>
            public override PrimitiveType primitiveType {
                get {
                    return _primitiveType;
                }
            }

            /// <summary>
            /// 获取当前成员的类型。
            /// </summary>
            public override MemberType memberType {
                get {
                    return MemberType.@struct;
                }
            }

            public PrimitiveTypeReference(string name, PrimitiveType primitiveType)
                : base(MemberType.@struct) {
                this.name = name;
                _primitiveType = primitiveType;
                baseClass = System_ValueType;
            }

            /// <summary>
            /// 将当前成员的完整限定名写入字符串缓存。
            /// </summary>
            /// <param name="buffer">用于写入的缓冲区对象。</param>
            public override void writeSignature(StringBuilder buffer) {
                buffer.Append(_primitiveType.getName());
            }

        }

        /// <summary>
        /// 获取预定义的字节类型。
        /// </summary>
        public static TypeReference System_Byte = new PrimitiveTypeReference("Byte", PrimitiveType.@byte);

        /// <summary>
        /// 获取预定义的 16 位有符号整数。
        /// </summary>
        public static TypeReference System_Int16 = new PrimitiveTypeReference("Int16", PrimitiveType.int16);

        /// <summary>
        /// 获取预定义的 16 位无符号整数。
        /// </summary>
        public static TypeReference System_UIint16 = new PrimitiveTypeReference("UInt16", PrimitiveType.uint16);

        /// <summary>
        /// 获取预定义的 Unicode 字符。
        /// </summary>
        public static TypeReference System_Char = new PrimitiveTypeReference("Char", PrimitiveType.@char);

        /// <summary>
        /// 获取预定义的 32 位有符号整数。
        /// </summary>
        public static TypeReference System_Int32 = new PrimitiveTypeReference("Int32", PrimitiveType.int32);

        /// <summary>
        /// 获取预定义的 32 位无符号整数。
        /// </summary>
        public static TypeReference System_UInt32 = new PrimitiveTypeReference("UInt32", PrimitiveType.uint32);

        /// <summary>
        /// 表示布尔型。
        /// </summary>
        public static TypeReference System_Bool = new PrimitiveTypeReference("Bool", PrimitiveType.@bool);

        /// <summary>
        /// 获取预定义的 32 位浮点数。
        /// </summary>
        public static TypeReference System_Float32 = new PrimitiveTypeReference("Float32", PrimitiveType.float32);

        /// <summary>
        /// 获取预定义的 64 位有符号整数。
        /// </summary>
        public static TypeReference System_Float64 = new PrimitiveTypeReference("Float64", PrimitiveType.float64);

        /// <summary>
        /// 获取预定义的 64 位有符号整数。
        /// </summary>
        public static TypeReference System_Int64 = new PrimitiveTypeReference("Int64", PrimitiveType.int64);

        /// <summary>
        /// 获取预定义的 64 位无符号整数。
        /// </summary>
        public static TypeReference System_UInt64 = new PrimitiveTypeReference("UInt64", PrimitiveType.uint64);

        #endregion

        #region 业务类型

        /// <summary>
        /// 获取预定义的 String 类型。
        /// </summary>
        public static TypeReference System_String = new InternalTypeReference("string") {
            baseClass = System_Object
        };

        /// <summary>
        /// 获取预定义的 Exception 类型。
        /// </summary>
        public static TypeReference System_Exception = new TypeReference(MemberType.@class) {
            name = "Exception",
            baseClass = System_Object
        };

        /// <summary>
        /// 获取预定义的 Range 类型。
        /// </summary>
        public static TypeReference System_Range = new TypeReference(MemberType.@struct) {
            name = "Range",
            baseClass = System_ValueType
        };

        /// <summary>
        /// 获取预定义的 IClosable 类型。
        /// </summary>
        public static TypeReference System_IClosable = new TypeReference(MemberType.@interface) {
            name = "IClosable"
        };

        /// <summary>
        /// 获取预定义的 Type 类型。
        /// </summary>
        public static TypeReference System_Reflection_Type = new TypeReference(MemberType.@class) {
            name = "Type",
            baseClass = System_ValueType
        };

        /// <summary>
        /// 获取预定义的 IEnumeratable&lt;T&gt; 类型。
        /// </summary>
        public static GenericTypeDefinitionReference System_Collections_IEnumeratable_T = new GenericTypeDefinitionReference(MemberType.@interface, T) {
            name = "IEnumeratable"
        };

        /// <summary>
        /// 获取预定义的 IEnumerator&lt;T&gt; 类型。
        /// </summary>
        public static GenericTypeDefinitionReference System_Collections_IEnumerator_T = new GenericTypeDefinitionReference(MemberType.@interface, T) {
            name = "IEnumerator"
        };

        /// <summary>
        /// 获取预定义的 List&lt;T&gt; 类型。
        /// </summary>
        public static GenericTypeDefinitionReference System_Collections_List_T = new GenericTypeDefinitionReference(MemberType.@class, T) {
            name = "List",
            baseClass = System_Object
        };

        /// <summary>
        /// 获取预定义的 IList&lt;T&gt; 类型。
        /// </summary>
        public static GenericTypeDefinitionReference System_Collections_IList_T = new GenericTypeDefinitionReference(MemberType.@interface, T) {
            name = "IList"
        };

        private static MemberReference.GenericParameter[] TKeyValue {
            get {
                return new MemberReference.GenericParameter[] {
                    new MemberReference.GenericParameter(){
                        name = "TKey"
                    },
                    new MemberReference.GenericParameter(){
                        name = "TValue"
                    }
                };
            }
        }

        /// <summary>
        /// 获取预定义的 Dict&lt;TKey, TValue&gt; 类型。
        /// </summary>
        public static GenericTypeDefinitionReference System_Collections_Dict_TKey_TValue = new GenericTypeDefinitionReference(MemberType.@class, TKeyValue) {
            name = "Dict",
            baseClass = System_Object
        };

        /// <summary>
        /// 获取预定义的 IDict&lt;TKey, TValue&gt; 类型。
        /// </summary>
        public static GenericTypeDefinitionReference System_Collections_IDict_TKey_TValue = new GenericTypeDefinitionReference(MemberType.@interface, TKeyValue) {
            name = "IDict",
            baseClass = System_Object
        };

        #endregion

        #region 初始化

        /// <summary>
        /// 从指定的包内导入并初始化相应的内置类型。
        /// </summary>
        public static void importFrom(ModuleReference target) {

            var system = importNamespace(target, "System");

            importType(system, System_Object);
            importType(system, System_ValueType);
            importType(system, System_Enum_T);
            importType(system, System_Ptr_T);
            importType(system, System_Array_T);
            importType(system, System_Func_T);
            importType(system, System_Tuple_T);

            importType(system, System_Byte);
            importType(system, System_UIint16);
            importType(system, System_Char);
            importType(system, System_Int32);
            importType(system, System_UInt32);
            importType(system, System_Bool);
            importType(system, System_Float32);
            importType(system, System_Float64);
            importType(system, System_Int64);
            importType(system, System_UInt64);

            importType(system, System_Func);
            importType(System_Func, System_Ref_T);
            importType(System_Func, System_Func_Out_T);

            importType(system, System_ImplicitAnnotation);
            importType(system, System_DeprecatedAnnotation);
            importType(system, System_RunTime_FieldOffsetAnnotation);

            importType(system, System_Exception);
            importType(system, System_IClosable);

            var text = importNamespace(system, "Text");

            var collections = importNamespace(system, "Collections");
            importType(collections, System_Collections_IEnumerator_T);
            importType(collections, System_Collections_List_T);
            importType(collections, System_Collections_Dict_TKey_TValue);

            var objDef = System_Object.definition as TypeDefinition;
            if (objDef != null) {
                //if (objDef.baseClasss != null) {
                //    Compiler.error(ErrorCode.none, String.Format("基础库中类型“{0}”不能显式继承", PredefinedTypes.System_Object.fullName), objDef.name);
                //}

                //// 强制设置 Object 不继承。
                //objDef.baseClasss = new List<Expression>() {
                //    new PredefinedTypeLiteral(){
                //        type = TokenType.@void
                //    }
                //};
            }

        }

        private static NamespaceReference importNamespace(NamespaceReference container, string name) {
            var exist = container.getMember(name, 0);
            if (exist != null && exist.memberType != MemberType.@namespace) {
                Compiler.error(ErrorCode.none, String.Format("编译基础库错误：“{0}”下已存在名为“{1}”的定义，无法声明命名空间", container.signature, name));
            }

            if (exist == null) {
                exist = new NamespaceReference();
                exist.name = name;

                container.addMember(exist);
            }

            return (NamespaceReference)exist;
        }

        private static void importType(NamespaceReference container, TypeReference type) {
            var exist = container.getMember(type.name, type.genericParameterCount);
            if (exist == null) {
                container.addMember(type);
                return;
            }

            // 如果已添加过则不再添加。
            if (exist == type) {
                return;
            }

            if (exist.memberType != type.memberType) {
                Compiler.error(ErrorCode.none, String.Format("编译基础库错误：“{0}”必须是一个“{1}”", exist.signature, type.memberType.getReadableName()));
                return;
            }

            if (exist.modifiers.hasFlag(Modifiers.@private | Modifiers.@protected)) {
                Compiler.error(ErrorCode.none, String.Format("编译基础库错误：{0}“{1}”必须是公开的", type.memberType.getReadableName(), type.signature));
                return;
            }

            if (exist.genericParameters != null) {
                for (int i = 0; i < exist.genericParameters.Length; i++) {
                    if (exist.genericParameters[i].name != type.genericParameters[i].name) {
                        Compiler.error(ErrorCode.none, String.Format("编译基础库错误：“{0}”的泛型形参名必须是“{1}”", type.signature, type.genericParameters[i].name));
                        return;
                    }
                }
            }

            type.definition = (TypeDefinition)exist.definition;
            exist.definition.reference = type;
            type.modifiers = exist.modifiers;
            type.members = ((NamespaceReference)exist).members;
            foreach (var vk in type.members) {
                for (var m = vk.Value; m != null; m = m.next) {
                    m.container = (NamespaceReference)type;
                }
            }

            container.addMember(type);
            container.removeMember(exist);

        }

        #endregion

    }

}